#pragma once
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <functional>
#include <iostream>

#include "Buffer.h"

namespace mylog
{
    enum class AsyncType
    {
        ASYNC_SAFE,
        ASYNC_UNSAFE
    };

    using functor = std::function<void(Buffer&)>;

    class AsyncWorker
    {
    public:
        using ptr = std::shared_ptr<AsyncWorker>;
        AsyncWorker(const functor& callback, AsyncType asyncType = AsyncType::ASYNC_SAFE);
        ~AsyncWorker();
        /**
         * 将待处理的数据加入生产者缓冲区
         * @param data 指向数据首字节的指针
         * @param len 数据的字节长度
         */
        void push(const char* data, size_t len);
        /**
         * 消费者将当前可处理的数据处理完成后，停止继续处理缓冲区
         */
        void stop();

    private:
        /**
         * 线程函数，若未停止，则不断地将生产者缓冲区和消费者缓冲区对调
         * 然后处理处于消费者缓冲区的数据
         */
        void consumer();

    private:
        AsyncType async_type_;
        std::atomic<bool> stop_;
        std::mutex mtx_; // 生产者缓冲区的互斥量
        mylog::Buffer buffer_producer_;
        mylog::Buffer buffer_consumer_;
        std::condition_variable cond_producer_;
        std::condition_variable cond_consumer_;
        std::thread worker_;
        functor callback_;
    }; // class AsyncWorker

} // namespace log